package com.yzl.frelink.service.matlab;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.yzl.frelink.entities.component.Chart;
import com.yzl.frelink.entities.model.Model;
import com.yzl.frelink.util.Commander;

@Service
public class MatlabCompiler {
    @Autowired
    ParameterCompiler parameterCompiler;
    @Autowired
    StateCompiler stateCompiler;
    @Autowired
    TransitionCompiler transitionCompiler;
    @Autowired
    ModelCompiler modelCompiler;
    @Value("${frelink.matCode}")
    private String matCode;
    @Value("${frelink.saveCode}")
    private String saveCode;
    public void compileToMatlab(Model model) {
        StringBuilder sb = new StringBuilder();
        sb.append(compileSystem(model));
        sb.append(compileStates(model));
        sb.append(compileTransitions(model));
        sb.append(compileParameters(model));
        sb.append(compileModel(model));
        sb.append(compileSaving());
        try{
            File file = new File("./public/out_model/generate_" + model.getName() + ".m");
            Writer writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
            writer.write(sb.toString());
            writer.close();
            Commander.generateSLX("./public/out_model/generate_" + model.getName() + ".m");
        } catch (Exception e) {
            System.out.println("Error writing to file: " + e.getMessage());
        }
    }

    private String compileSystem(Model model) {
        List<String> components = new ArrayList<>();
        int chartCount = model.getChartNum();
        for (Chart chart : model.getCharts()) {
            components.add("\"/" + chart.getName() + "\"");
            chart.setValidStatesCompilingOrder();
        }
        String chartNames = String.join(",", components);
        StringBuilder sb = new StringBuilder();
        sb.append("function generate_").append(model.getName()).append("()\n");
        sb.append("bdclose('all');\nmyModel = '").append(model.getName()).append("';\n");
        sb.append("new_system(myModel);\nchartSize = ").append(chartCount).append(";\n");
        sb.append("chartNames = [").append(chartNames).append("];\n");
        sb.append(matCode);
        return sb.toString();
//         return """
// function generate_%s()
// bdclose('all');
// myModel = '%s';
// new_system(myModel);
// chartSize = %s;
// chartNames = [%s];
// for i = 1 : chartSize
//   add_block('sflib/Chart', myModel+chartNames(i));
// end
// rt = sfroot;
// charts = find(rt, '-isa', 'Stateflow.Chart');
// """.formatted(model.getName(), model.getName(), chartCount, chartNames);
    }

    public String compileStates(Model model) {
        return stateCompiler.compileStates(model);
    }

    public String compileTransitions(Model model) {
        return transitionCompiler.compileTransitions(model);
    }

    public String compileParameters(Model model) {
        return parameterCompiler.compileParameters(model);
    }

    public String compileModel(Model model) {
        return modelCompiler.compileModel(model);
    }
    private String compileSaving() {
        return saveCode;
//     return """
// % create the subSystem
// % bh = Simulink.findBlocks(myModel);
// % Simulink.BlockDiagram.createSubsystem(bh);

// Simulink.BlockDiagram.arrangeSystem(myModel);
// save_system;
// end  
// """;
    }
}
